package menu

import (
	"errors"
	"fmt"
	"github.com/xinglou123/pkg/db/xorm"
	"github.com/xinglou123/pkg/os/conv"
	"github.com/xinglou123/pkg/utils"
	"sync"
)

type Menu struct {
	Id         int64  `xorm:"pk autoincr 'id'" form:"id" json:"id"`
	Name       string `xorm:"char(60)" form:"name" json:"name"`
	Icon       string `xorm:"char(60)" form:"icon" json:"icon"`
	Href       string `xorm:"char(50)" form:"href" json:"href"`
	Pid        int64  `xorm:"int(11)" form:"pid" json:"pid"`
	Sort       int64  `xorm:"int(11)" form:"sort" json:"sort"`
	Status     string `xorm:"char(20)" form:"status" json:"status"`
	Deleted_at string `xorm:"DateTime deleted" form:"deleted_at" json:"-" time_format:"2006-01-02 15:04:05"`
	Created_at string `xorm:"DateTime created" form:"created_at" json:"-" time_format:"2006-01-02 15:04:05"`
	Updated_at string `xorm:"DateTime updated" form:"updated_at" json:"-" time_format:"2006-01-02 15:04:05"`
}

type Tree struct {
	Id     int64  `xorm:"pk autoincr 'id'" form:"id" json:"id"`
	Name   string `xorm:"char(60)" form:"name" json:"name"`
	Icon   string `xorm:"char(60)" form:"icon" json:"icon"`
	Href   string `xorm:"char(50)" form:"href" json:"href"`
	Pid    int64  `xorm:"int(11)" form:"pid" json:"pid"`
	Sort   int64  `xorm:"int(11)" form:"sort" json:"sort"`
	Status string `xorm:"char(20)" form:"status" json:"status"`
	Childs []Tree `xorm:"-" json:"childs,omitempty"`
}

// MenuService
var MenuService = &menuService{
	mutex: &sync.Mutex{},
}

//menuService ...
type menuService struct {
	mutex *sync.Mutex
}

//根据Id 获取
func (service *menuService) One(uid int64) (*Menu, error) {
	service.mutex.Lock()
	defer service.mutex.Unlock()
	if uid == 0 {
		return nil, errors.New("缺少参数")
	}
	var menu Menu
	orm := xorm.MustDB()
	_, err := orm.Id(uid).Get(&menu)
	return &menu, err
}
func (service *menuService) Query(param map[string]interface{}) ([]Menu, *utils.Page, error) {
	service.mutex.Lock()
	defer service.mutex.Unlock()

	orm := xorm.MustDB()
	t := orm.Where("id>0")

	if path, ok := param["name"]; ok {
		//存在
		if len(path.(string)) > 0 {
			t = t.Where("name like ?", "%"+path.(string)+"%")
		}
	}
	var menu []Menu
	var page int = 1
	if pagek, ok := param["page"]; ok {
		page = conv.Int(pagek)
	}
	var limit int = 10
	if limitk, ok := param["limit"]; ok {
		limit = conv.Int(limitk)
		if limit == 0 {
			limit = 10
		}
	}
	offset := (page - 1) * limit
	count, err := t.Limit(limit, offset).FindAndCount(&menu)
	if err != nil {
		return menu, nil, err
	}
	return menu, utils.NewPage(page, limit, conv.Int(count)), err
}

//
func (service *menuService) Add(menu Menu) (m Menu, err error) {
	service.mutex.Lock()
	defer service.mutex.Unlock()

	orm := xorm.MustDB()
	session := orm.NewSession()
	defer session.Close()
	serr := session.Begin()

	_, serr = session.InsertOne(menu)
	if serr != nil {
		err = errors.New("添加失败")
		session.Rollback()
		return m, err
	}
	serr = session.Commit()
	if serr != nil {
		err = errors.New("添加失败")
		return m, err
	}
	_, err = orm.Where("name = ?", menu.Name).Get(&m)

	return m, err

}

/**
* 删除
*
* @param  int
 */
func (service *menuService) Delete(uid int64) (int64, error) {
	service.mutex.Lock()
	defer service.mutex.Unlock()
	if uid == 0 {
		return 0, errors.New("不能删除该记录")
	}
	var menu Menu
	orm := xorm.MustDB()
	iid, err := orm.Id(uid).Delete(menu)
	return iid, err
}

/**
* 更新
*
* @param  int
* @return int
 */
func (service *menuService) Update(menu Menu) (iid int64, err error) {
	service.mutex.Lock()
	defer service.mutex.Unlock()

	if menu.Id == 0 {
		return 0, errors.New("不能修改该记录")
	}
	orm := xorm.MustDB()
	session := orm.NewSession()
	defer session.Close()
	err = session.Begin()

	//menu.Status = "0"
	iid, err = session.Where("id = ?", menu.Id).AllCols().Update(menu)
	if err != nil {
		err = errors.New("更新失败")
		fmt.Println(err)
		session.Rollback()

		return iid, err
	}
	err = session.Commit()
	if err != nil {
		fmt.Println(err)
		err = errors.New("更新失败")
		return 0, err
	}
	return iid, err

}

//Count
func (service *menuService) Count() (int64, error) {
	service.mutex.Lock()
	defer service.mutex.Unlock()

	var menu Menu
	orm := xorm.MustDB()
	total, err := orm.Count(menu)
	return total, err
}

//返回菜单树
func (service *menuService) MenuTree() (nodes []Tree) {

	menus := make([]Menu, 0)
	//获取父节点
	orm := xorm.MustDB()
	orm.Where("status = 1").Asc("sort").Find(&menus)

	//初始化菜单Map
	Tree_list := make(map[int64][]Tree)

	for _, menu := range menus {
		if _, ok := Tree_list[menu.Pid]; !ok {
			Tree_list[menu.Pid] = make([]Tree, 0)
		}
		tree := Tree{
			Id:     menu.Id,
			Name:   menu.Name,
			Icon:   menu.Icon,
			Href:   menu.Href,
			Pid:    menu.Pid,
			Sort:   menu.Sort,
			Status: menu.Status,
		}
		Tree_list[menu.Pid] = append(Tree_list[menu.Pid], tree)
	}
	for _, menu := range Tree_list[0] {
		for _, menu_second := range Tree_list[menu.Id] {
			if menu.Id == menu_second.Pid {
				menu.Childs = append(menu.Childs, menu_second)
			}
		}
		nodes = append(nodes, menu)
	}
	return nodes
}

//按父ID查找菜单子项
func (service *menuService) GetMenu(pid int64) []Menu {

	menus := make([]Menu, 0)
	//获取父节点
	orm := xorm.MustDB()
	orm.Where("status = 1 and pid = ？", pid).Find(&menus)

	return menus
}

//获取所有菜单
func (service *menuService) GetMenuAll() map[int64][]Menu {

	menus := make([]Menu, 0)
	//获取父节点
	orm := xorm.MustDB()
	orm.Where("status = 1").Find(&menus)
	//初始化菜单Map
	menu_list := make(map[int64][]Menu)

	for _, menu := range menus {
		if _, ok := menu_list[menu.Pid]; !ok {
			menu_list[menu.Pid] = make([]Menu, 0)
		}
		menu_list[menu.Pid] = append(menu_list[menu.Pid], menu)
	}

	return menu_list
}
